home *** CD-ROM | disk | FTP | other *** search
- /*
- file RenderingWindow.c
-
- Description:
- This file contains the routines used to manage the windows displayed
- by the HTMLSample application.
-
- HTMLSample is an application illustrating how to use the new
- HTMLRenderingLib services found in Mac OS 9. HTMLRenderingLib
- is Apple's light-weight HTML rendering engine capable of
- displaying HTML files.
-
- by John Montbriand, 1999.
-
- Copyright: © 1999 by Apple Computer, Inc.
- all rights reserved.
-
- Disclaimer:
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
-
- Change History (most recent first):
- 10/16/99 created by John Montbriand
- */
-
- #include "RenderingWindow.h"
-
- #include <HTMLRendering.h>
- #include <Resources.h>
- #include <StdDef.h>
- #include <string.h>
- #include <Sound.h>
-
- #include "History.h"
- #include "CIconButtons.h"
- #include "SampleUtils.h"
- #include "HTMLSample.h"
-
-
- /* resource id numbers for PICT resources used
- for drawing the fill area to the right of the buttons */
- enum {
- kLeftBarPicture = 128,
- kCenterBarPicture = 129,
- kRightBarPicture = 130
- };
-
- /* ASCII codes for the arrow keys on the keyboard */
- enum {
- kLeftArrowKey = 28,
- kUpArrowKey = 30,
- kDownArrowKey = 29
- };
-
- /* color icon button resources for the default
- navigation buttons. */
- enum {
- kBackDefaultButton = 128,
- kHomeDefaultButton = 129,
- kForwardDefaultButton = 130
- };
-
- /* constants used for adding custom buttons. */
- enum {
- kExtraButtonsMax = 4,
- kExtraButtonsListID = 128
- };
-
- /* the resource id for the main window's
- WIND resource. */
- enum {
- kRenderingWindowID = 128
- };
-
-
-
-
- /* RWindowHandle's refer to a data structure created
- for each rendering window to store various state
- variables used for maintaining the window on the
- screen. Most importantly, for this example, this
- is where a reference to the HTML rendering object
- is stored. A handle to this structure is stored in
- the rendering window's refcon field. */
-
- typedef struct RWindowStruct RWindowVars;
- typedef RWindowVars **RWindowHandle;
-
- struct RWindowStruct {
- RWindowHandle prev, next; /* list of open rendering windows */
- WindowPtr rwindow; /* a pointer to the window */
- HRReference renderer; /* a reference to the rendering object */
- HistoryDataHandle history; /* history of visited links for this window */
- Boolean isActive; /* true when this window is the frontmost window. */
- CIconButtonHandle bback, bhome, bforward; /* the default buttons */
- short nExtraButtons; /* the number of extra buttons */
- CIconButtonHandle extraButtons[1]; /* handles to the extra buttons */
- };
-
-
- /* these picture handles are used for drawing the fill area
- to the right of the buttons in the top of the window. The
- resources these variables reference are read in when
- InitRenderingWindows is called. */
- PicHandle gFBLeft = NULL, gFBCenter = NULL, gFBRight = NULL;
-
-
- /* a list of open rendering windows. */
- RWindowHandle gRWFirst = NULL, gRWLast = NULL;
-
-
- /* the global history is used to store 'all' visited links for
- every window. */
- HistoryDataHandle gGlobalHistory = NULL;
-
-
- /* gRenderingWindowsOpen is set to true when InitRenderingWindows
- is successful. */
- Boolean gRenderingWindowsOpen = false;
-
-
- /* InitRenderingWindows is called to initialize the environment used by
- routines defined in this file. It should be called before any of the
- other routines defined in this file are called. */
- OSStatus InitRenderingWindows(void) {
- /* get the pictures for drawing the fill
- area to the right of the buttons from the
- resource file */
- gFBLeft = GetPicture(kLeftBarPicture);
- if (gFBLeft == NULL) return resNotFound;
- gFBCenter = GetPicture(kCenterBarPicture);
- if (gFBCenter == NULL) return resNotFound;
- gFBRight = GetPicture(kRightBarPicture);
- if (gFBRight == NULL) return resNotFound;
- /* initialize the list of opened windows */
- gRWFirst = gRWLast = NULL;
- /* allocate the global history */
- gGlobalHistory = NewHistory();
- if (gGlobalHistory == NULL) return memFullErr;
- /* set the open flag */
- gRenderingWindowsOpen = true;
- /* done */
- return noErr;
- }
-
-
- /* CloseRenderingWindows closes any open rendering windows and
- deallocates any structures allocated when InitRenderingWindows
- was called. */
- OSStatus CloseRenderingWindows(void) {
- if (gRenderingWindowsOpen) {
- /* close any open rendering windows */
- while (gRWFirst != NULL)
- RWCloseWindow((**gRWFirst).rwindow);
- /* release the global history */
- DisposeHistory(gGlobalHistory);
- /* reset the open flag */
- gRenderingWindowsOpen = false;
- }
- return noErr;
- }
-
-
-
- /* MyHRURLToFSSpecProc is the URL to FSSpec mapping defined for rendering windows.
- it calls the HTMLRenderingLib HRUtilGetFSSpecFromURL routine to map the url
- to a FSSpec and then it checks to see if the file exists and if it's an application.
- If the file does not exist, it re-directs the URL to refer to the error page. If the
- file exists and it's an application, it launches the application. */
- static OSStatus MyHRURLToFSSpecProc(const char *rootURL, const char *linkURL,
- FSSpec *fsspec, URLSourceType urlSourceType, void *refCon) {
- RWindowHandle rwv;
- FSSpec spec;
- OSStatus err;
- FInfo fndrInfo;
- /* set up locals */
- rwv = (RWindowHandle) refCon;
- /* as the rendering library to map the file
- for us. */
- err = HRUtilGetFSSpecFromURL(rootURL, linkURL, &spec);
- if (err != noErr) goto bail;
- /* check to see if the file exists. */
- err = FSpGetFInfo(&spec, &fndrInfo);
- if (err != noErr) goto bail;
- /* if the file is an application, launch it */
- if (fndrInfo.fdType == 'APPL') {
- LaunchParamBlockRec launchpb;
- memset(&launchpb, 0, sizeof(launchpb));
- launchpb.launchBlockID = extendedBlock;
- launchpb.launchEPBLength = extendedBlockLen;
- launchpb.launchFileFlags = launchNoFileFlags;
- launchpb.launchControlFlags = launchContinue;
- launchpb.launchAppSpec = &spec;
- err = LaunchApplication(&launchpb);
- /* we return an error so the HTMLRenderingLib
- does not try to draw the file. */
- return fnfErr;
- }
- /* return the FSSpec */
- *fsspec = spec;
- return noErr;
- bail:
- /* if an error occured and we're looking for a
- HTML source file, then we re-direct the URL to the
- error file. */
- if (urlSourceType == kHRLookingForHTMLSource) {
- Handle rootURL, errorLink;
- /* the link we have in our resources is application
- relative, so we need to get the application's URL first. */
- if (GetApplicationFolderURL(&rootURL) == noErr) {
- /* and then we pull the application relative link
- from the resource file. */
- errorLink = GetResource(kCStyleStringResourceType, kErrorPageURLString);
- if (errorLink != NULL) {
- HLock(errorLink);
- HLock(rootURL);
- /* after retrieving the URL and the link, we ask the
- rendering library to map them to a FSSpec. */
- if (HRUtilGetFSSpecFromURL(*rootURL, *errorLink, &spec) == noErr) {
- /* then, if the file exists, we return a FSSpec referring
- to the error file. */
- if (FSpGetFInfo(&spec, &fndrInfo) == noErr) {
- *fsspec = spec;
- err = noErr;
- }
- }
- HUnlock(errorLink);
- }
- DisposeHandle(rootURL);
- }
- }
- return err;
- }
-
-
- /* RedrawWindowButtons redraws the three default buttons in the top
- of the window. the way they are drawn depends on what commands
- are available at the time when this routine is called. here we set the
- origin to 0,0, and the clip region to the window's clip region. We
- do so because when this routine is called the origin and clip region
- may have been left in an unknown state by the rendering library.*/
- static void RedrawWindowButtons(RWindowHandle rwv) {
- RgnHandle clipsave;
- /* set the current grafport to the window's */
- SetPort((**rwv).rwindow);
- /* set the origin before drawing. it may be incorrect when we're called. */
- SetOrigin(0, 0);
- /* save the clipping region going to links with anchors sets it incorrectly */
- clipsave = NewRgn();
- GetClip(clipsave);
- ClipRect(&(**rwv).rwindow->portRect);
- /* draw the buttons */
- DrawCIconButton((**rwv).bback, (CanGoBack((**rwv).history) ? kCBup : kCBdisabled));
- DrawCIconButton((**rwv).bhome, (CanGoHome((**rwv).history) ? kCBup : kCBdisabled));
- DrawCIconButton((**rwv).bforward, (CanGoForward((**rwv).history) ? kCBup : kCBdisabled));
- /* restore the clipping region */
- SetClip(clipsave);
- DisposeRgn(clipsave);
- }
-
-
- /* MyNewURLProc is called by the rendering library whenever a new HTML file
- is brought into the display. This routine will be called with the HTML file's
- URL. if addToHistory is true, then the file is added to the history of visited
- links. */
- static OSStatus MyNewURLProc( const char *url, const char *targetFrame,
- Boolean addToHistory, void *refCon, HRNewURLUPP userUPP) {
- RWindowHandle rwv;
- Str255 title;
- Point theSize;
- /* set up locals */
- rwv = (RWindowHandle) refCon;
- /* set up the drawing environment */
- SetPort((**rwv).rwindow);
- SetOrigin(0, 0);
- /* set the window's title to the new file */
- if (HRGetTitle( (**rwv).renderer, title) == noErr)
- SetWTitle((**rwv).rwindow, title);
- else title[0] = 0;
- /* set the window's standard state rectangle to
- the 'best' size for displaying this page. If the user
- zooms the window, it will go to this size. */
- if (HRGetRenderedImageSize((**rwv).renderer, &theSize) == noErr)
- SetWindowStandardStateSize((**rwv).rwindow, theSize.h + 16, theSize.v + 32 + 16);
- /* if add to history is true, then we add the URL to both
- the window's history and to the global history. */
- if (addToHistory) {
- /* add to the window's history */
- AddToHistory((**rwv).history, url, title);
- /* add tot the global history. */
- AddToHistory(gGlobalHistory, url, "\p");
- /* redraw the window's controls. We do
- this here because their visual state depends
- on the state of the window's history. */
- RedrawWindowButtons(rwv);
- }
- /* done */
- return noErr;
- }
-
-
- /* MyHRWasURLVisitedProc is called by the HTML rendering library
- when it would like to determine if a link has been visited. This
- information is used when drawing links. */
- static Boolean MyHRWasURLVisitedProc(const char *url, void *refCon) {
- /* here we return true if the link can be found in the
- global history of all visited links, not just the window's history. */
- return InHistory(gGlobalHistory, url);
- }
-
-
- /* URLContainsAnchor returns true if a URL contains
- an anchor. i.e. it contains a # character. */
- static Boolean URLContainsAnchor(char const *url) {
- char const *cp;
- for (cp = url; *cp != '\0'; cp++)
- if (*cp == '#')
- return true;
- return false;
- }
-
-
- /* RWGotoURL displays HTML file referred to by the url in the
- rendering window. if addToHistory is true, then the window
- will be added to the window's history list. */
- OSStatus RWGotoURL(WindowPtr rWin, char* url, Boolean addToHistory) {
- RWindowHandle rwv;
- OSStatus err;
- Point origin = {0, 0};
- Rect donedrawingbox;
- /* set up locals */
- rwv = (RWindowHandle) GetWRefCon(rWin);
-
- /* if the URL does not contain an anchor, then scroll
- the HTML view to the origin. */
- if ( ! URLContainsAnchor(url)) {
- err = HRScrollToLocation((**rwv).renderer, &origin);
- if (err != noErr) goto bail;
- }
- /* ask the rendering object to display the HTML page
- referred to by the URL. note, we pass the addToHistory to
- this routine which in turn passes it to our MyNewURLProc
- routine. */
- err = HRGoToURL((**rwv).renderer, url, addToHistory, false);
- if (err != noErr) goto bail;
-
- /* draw the new page */
- err = HRDraw((**rwv).renderer, NULL);
- if (err != noErr) goto bail;
-
- /* if addToHistory is false, then we would not
- have re-drawn the buttons inside of our MyNewURLProc
- routine so we should draw them here. */
- if ( ! addToHistory)
- RedrawWindowButtons(rwv);
-
- /* we validate the areas that were drawn by this
- routine. This is to avoid unnecessary redraws when
- the window is first opened. When the window is opened,
- an update event will be posted for its entire contents.
- These calls prevent the areas we have just drawn from
- being re-drawn when the update event is processed. */
- SetRect(&donedrawingbox, 0, 0, 32*3, 32);
- ValidRect(&donedrawingbox);
- donedrawingbox = rWin->portRect;
- donedrawingbox.top += 33;
- ValidRect(&donedrawingbox);
-
- /* done */
- return noErr;
- bail:
- return err;
- }
-
- void debugf(char const *fmt, ...);
-
- /* RWGotoAppRelLink displays HTML file referred to by the application
- relative link in the rendering window. if addToHistory is true, then
- the window will be added to the window's history list. */
- OSStatus RWGotoAppRelLink(WindowPtr rWin, char* linkstr, Boolean addToHistory) {
-
- OSStatus err;
- Handle rootURL, fullURL;
- /* set up our locals */
- rootURL = fullURL = NULL;
- /* get the URL for the application's folder */
- err = GetApplicationFolderURL(&rootURL);
- if (err != noErr) goto bail;
- /* allocate a handle for storing the full URL */
- fullURL = NewHandle(0);
- if (fullURL == NULL) { err = memFullErr; goto bail; }
- /* ask the HTML rendering library to combine
- the url and the link to make a complete URL */
- HLock(rootURL);
- err = HRUtilCreateFullURL(*rootURL, linkstr, fullURL);
- if (err != noErr) goto bail;
- HUnlock(rootURL);
- /* call the RWGotoURL to bring the HTML file into view. */
- MoveHHi(fullURL);
- HLock(fullURL);
- err = RWGotoURL(rWin, *fullURL, addToHistory);
- if (err != noErr) goto bail;
- /* clean up our locals */
- DisposeHandle(rootURL);
- DisposeHandle(fullURL);
- /* done */
- return noErr;
- bail:
- /* on error, clean up and return the error. */
- if (rootURL != NULL) DisposeHandle(rootURL);
- if (fullURL != NULL) DisposeHandle(fullURL);
- return err;
- }
-
-
- /* GoBackCommand is called whenever the user chooses
- 'go back' by either picking the menu item, clicking on
- the button, or using the left arrow key on the keyboard. */
- static void GoBackCommand(RWindowHandle rwv) {
- char** theURL;
- /* get previous the URL from the window's history. */
- if (GoBack((**rwv).history, (Handle*) &theURL) == noErr) {
- MoveHHi((Handle) theURL);
- HLock((Handle) theURL);
- /* call the RWGotoURL routine to bring the
- HTML file referred to by the URL into view. */
- RWGotoURL((**rwv).rwindow, *theURL, false);
-
- DisposeHandle((Handle) theURL);
- }
- }
-
- /* GoHomeCommand is called whenever the user chooses
- 'go home' by either picking the menu item, clicking on
- the button, or using the left arrow key on the keyboard.
- The file opened by this command will be the first file
- displayed in the window when it was opened. */
- static void GoHomeCommand(RWindowHandle rwv) {
- char** theURL;
- /* get first the URL from the window's history. */
- if (GoHome((**rwv).history, (Handle*) &theURL) == noErr) {
- MoveHHi((Handle) theURL);
- HLock((Handle) theURL);
- /* call the RWGotoURL routine to bring the
- HTML file referred to by the URL into view. */
- RWGotoURL((**rwv).rwindow, *theURL, false);
-
- DisposeHandle((Handle) theURL);
- }
- }
-
-
- /* GoForwardCommand is called whenever the user chooses
- 'go forward' by either picking the menu item, clicking on
- the button, or using the left arrow key on the keyboard. */
- static void GoForwardCommand(RWindowHandle rwv) {
- char** theURL;
- /* get next the URL from the window's history. */
- if (GoForward((**rwv).history, (Handle*) &theURL) == noErr) {
- MoveHHi((Handle) theURL);
- HLock((Handle) theURL);
- /* call the RWGotoURL routine to bring the
- HTML file referred to by the URL into view. */
- RWGotoURL((**rwv).rwindow, *theURL, false);
-
- DisposeHandle((Handle) theURL);
- }
- }
-
-
- /* RWGoToButtonPage is called whenever the user clicks on
- a custom button. This routine attempts to load the
- application relative URL stored in the button's string
- data. */
- static OSStatus RWGoToButtonPage(WindowPtr rWin, CIconButtonHandle theButton) {
- RWindowHandle rwv;
- OSStatus err;
- Handle linkURL;
- /* set up locals */
- linkURL = NULL;
- rwv = (RWindowHandle) GetWRefCon(rWin);
- /* get the application relative link from the button */
- err = GetCIconButtonStringData(theButton, &linkURL);
- if (err != noErr) goto bail;
- /* call RWGotoAppRelLink to bring the HTML file
- referred to by the link into the display. */
- MoveHHi(linkURL);
- HLock(linkURL);
- err = RWGotoAppRelLink(rWin, *linkURL, true);
- if (err != noErr) goto bail;
- /* clean up */
- DisposeHandle(linkURL);
- /* done */
- return noErr;
- bail:
- if (linkURL != NULL) DisposeHandle(linkURL);
- return err;
- }
-
-
-
- /* DrawFillBar draws the fill area to the right of the
- button controls in the top of the window. */
- static OSStatus DrawFillBar(Rect *bounds) {
- Rect r;
- /* Draw the left side */
- r = *bounds;
- r.right = r.left + 8;
- DrawPicture(gFBLeft, &r);
- /* draw the center */
- r = *bounds;
- r.left += 8;
- r.right -= 8;
- DrawPicture(gFBCenter, &r);
- /* draw the right side */
- r = *bounds;
- r.left = r.right - 8;
- DrawPicture(gFBRight, &r);
- /* done */
- return noErr;
- }
-
-
-
- /* RWUpdate should be called in response to an update event.
- it calls BeginUpdate and EndUpdate redrawing the window's
- contents as necessary. */
- void RWUpdate(WindowPtr rWin) {
- RWindowHandle rwv;
- Rect r;
- short i;
- /* set up locals */
- rwv = (RWindowHandle) GetWRefCon(rWin);
-
- /* set up the drawing environment */
- SetPort(rWin);
- SetOrigin(0, 0);
- ClipRect(&rWin->portRect);
- BeginUpdate(rWin);
-
- /* draw the button controls and the fill area at the top of the window. */
- SetRect(&r, 32*(3+(**rwv).nExtraButtons), 0, rWin->portRect.right, 32);
- DrawFillBar(&r);
- RedrawWindowButtons(rwv);
- for (i=0; i<(**rwv).nExtraButtons; i++)
- DrawCIconButton((**rwv).extraButtons[i], kCBup);
-
- /* draw a one pixel border at the bottom of that area */
- MoveTo(0, 32);
- LineTo(rWin->portRect.right-1, 32);
-
- /* if the window is not active, then gray out everything we
- just drew. */
- if ( ! (**rwv).isActive) {
- SetRect(&r, 0, 0, rWin->portRect.right, 33);
- GrayOutBox(&r);
- }
-
- /* draw the grow icon */
- DrawGrowIconWithoutScrollLines(rWin);
-
- /* draw the HTML image. we do this last as the time it takes
- to complete may vary depending on the HTML content in the window.
- This way, the window's structure and controls look solid and they
- redraw in a consistent way. */
- HRDraw((**rwv).renderer, rWin->visRgn);
-
- /* reset the drawing enviroment */
- SetOrigin(0, 0);
- EndUpdate(rWin);
- }
-
-
-
- /* RWActivate should be called in response to activate events.*/
- void RWActivate(WindowPtr rWin, Boolean activate) {
- RWindowHandle rwv;
- Rect r;
- /* set up locals */
- rwv = (RWindowHandle) GetWRefCon(rWin);
- /* set the active flag in the window's variables */
- (**rwv).isActive = activate;
- /* call the rendering library to activate or
- deactivate the HTML object */
- if (activate)
- HRActivate((**rwv).renderer);
- else HRDeactivate((**rwv).renderer);
- /* post an update event so the grow icon
- and the controls are re-drawn to reflect
- the new active/inactive state. */
- SetPort(rWin);
- SetOrigin(0, 0);
- SetRect(&r, 0, 0, rWin->portRect.right, 33);
- InvalRect(&r);
- /* ...and the grow box */
- SetRect(&r, 0, 0, 16, 16);
- OffsetRect(&r, rWin->portRect.right-16, rWin->portRect.bottom-16);
- InvalRect(&r);
- }
-
-
- /* RWRecalculateSize should be called whenever the size of a rendering
- window changes. This routine resizes and redraws the windows
- contents appropriately. */
- void RWRecalculateSize(WindowPtr rWin) {
- RWindowHandle rwv;
- Rect r;
- /* set up locals */
- rwv = (RWindowHandle) GetWRefCon(rWin);
- /* set up the drawing environment */
- SetPort(rWin);
- SetOrigin(0, 0);
- /* reset the html object's rendering area */
- r = rWin->portRect;
- SetRect(&r, r.left, r.top+33, r.right+1, r.bottom+1);
- HRSetRenderingRect((**rwv).renderer, &r);
- }
-
-
- /* RWResetGotoMenu should be called before calling MenuKey or MenuSelect. It
- enables the back, forward, and home menu commands depending on what
- commands are available and it rebuilds the history list at the bottom
- of the go to menu. */
- void RWResetGotoMenu(WindowPtr rWin) {
- RWindowHandle rwv;
- MenuHandle goMenu;
- /* set up locals */
- rwv = (RWindowHandle) GetWRefCon(rWin);
- goMenu = GetMenuHandle(mGo);
- /* enable the back command */
- if (CanGoBack((**rwv).history))
- EnableItem(goMenu, iBack);
- else DisableItem(goMenu, iBack);
- /* enable the forward command */
- if (CanGoForward((**rwv).history))
- EnableItem(goMenu, iForward);
- else DisableItem(goMenu, iForward);
- /* enable the home command */
- if (CanGoHome((**rwv).history))
- EnableItem(goMenu, iHome);
- else DisableItem(goMenu, iHome);
- /* remove any items at the bottom of the menu */
- while (CountMItems(goMenu) >= iGoSep)
- DeleteMenuItem(goMenu, iGoSep);
- /* append this window's history to the menu */
- AppendHistoryToMenu((**rwv).history, goMenu);
- }
-
-
- /* RWHandleGotoMenu should be called when an item is chosen from the
- go to menu. item is the number of the item that was chosen. */
- void RWHandleGotoMenu(WindowPtr rWin, short item) {
- RWindowHandle rwv;
- /* set up locals */
- rwv = (RWindowHandle) GetWRefCon(rWin);
- /* err, this first part is pretty obvious...*/
- if (item == iBack) {
- GoBackCommand(rwv);
- } else if (item == iForward) {
- GoForwardCommand(rwv);
- } else if (item == iHome) {
- GoHomeCommand(rwv);
- } else if (item > iGoSep) {
- char** theURL;
- /* if one of the history items is chosen from the bottom of
- the menu, then we retrieve that item from the window's
- history and call HRGoToURL to display it. */
- if (GoToMenuItem((**rwv).history, (Handle*) &theURL, item - iGoSep) == noErr) {
- MoveHHi((Handle) theURL);
- HLock((Handle) theURL);
- HRGoToURL((**rwv).renderer, *theURL, false, true);
- SetPort(rWin);
- RedrawWindowButtons(rwv);
- DisposeHandle((Handle) theURL);
- }
- }
- }
-
-
- /* RWHandleMouseDown should be called in response to mouse down
- events occuring inside of a rendering window. This routine responds
- to mouse clicks in the controls at the top of the window. */
- void RWHandleMouseDown(WindowPtr rWin, Point where) {
- RWindowHandle rwv;
- /* set up locals */
- rwv = (RWindowHandle) GetWRefCon(rWin);
- SetPort(rWin);
- SetOrigin(0, 0);
- ClipRect(&rWin->portRect);
-
- /* handle clicks in the standard buttons */
- if (TrackCIconButton((**rwv).bback, where)) {
-
- GoBackCommand(rwv);
-
- } else if (TrackCIconButton((**rwv).bhome, where)) {
-
- GoHomeCommand(rwv);
-
- } else if (TrackCIconButton((**rwv).bforward, where)) {
-
- GoForwardCommand(rwv);
-
- } else {
- /* if a user clicks in a custom button, then we
- go to the link specified in it's data */
- short i;
- for (i=0; i<(**rwv).nExtraButtons; i++) {
- if (TrackCIconButton((**rwv).extraButtons[i], where)) {
- OSStatus err;
- err = RWGoToButtonPage(rWin, (**rwv).extraButtons[i]);
- /* report errors here */
- DrawCIconButton((**rwv).extraButtons[i], kCBup);
- break;
- }
-
- }
- }
- }
-
-
- /* RWKeyDown should be called for keydown events when a rendering
- window is the frontmost window. This routine maps the left, up,
- and right arrow keys to the back, home, and forward commands. */
- void RWKeyDown(WindowPtr rWin, char theKey) {
- RWindowHandle rwv;
- rwv = (RWindowHandle) GetWRefCon(rWin);
- SetPort(rWin);
- SetOrigin(0, 0);
- ClipRect(&rWin->portRect);
- switch (theKey) {
- case kLeftArrowKey: /* left arrow key */
- if (CanGoBack((**rwv).history)) {
- DrawCIconButton((**rwv).bback, kCBdown);
- GoBackCommand(rwv);
- }
- break;
- case kUpArrowKey: /* up arrow key */
- if (CanGoHome((**rwv).history)) {
- DrawCIconButton((**rwv).bhome, kCBdown);
- GoHomeCommand(rwv);
- }
- break;
- case kDownArrowKey: /* right arrow key */
- if (CanGoForward((**rwv).history)) {
- DrawCIconButton((**rwv).bforward, kCBdown);
- GoForwardCommand(rwv);
- }
- break;
- }
- }
-
-
- /* RWOpen opens a new, empty rendering window. If successful,
- then *rWindow will contain a pointer to a newly created window. */
- OSStatus RWOpen(WindowPtr *rWindow) {
- OSStatus err;
- WindowPtr rwin;
- short i, nExtraButtons;
- HRReference rend; /* the window's rendering object */
- HistoryDataHandle hist; /* the window's history */
- RWindowHandle rwv; /* storage for the window's state variables */
- RBCLRsrcHandle extraButtonIDs; /* extra button id list */
- CIconButtonHandle backButton, homeButton, forwardButton;
- CIconButtonHandle extraButtons[kExtraButtonsMax];
- /* static globals */
- static HRNewURLUPP gNewURLUPP = NULL;
- static HRWasURLVisitedUPP gVisitedURLUPP = NULL;
- static HRURLToFSSpecUPP gTranslateURLUPP = NULL;
- static Point gPosition = { 0, 0};
-
- /* set up locals */
- rwin = NULL;
- rend = NULL;
- hist = NULL;
- rwv = NULL;
- backButton = homeButton = forwardButton = NULL;
- for (i=0; i<kExtraButtonsMax; i++) extraButtons[i] = NULL;
- nExtraButtons = 0;
-
- /* get the buttons */
- backButton = NewCIconButton(kBackDefaultButton);
- if (backButton == NULL) { err = resNotFound; goto bail; }
- homeButton = NewCIconButton(kHomeDefaultButton);
- if (homeButton == NULL) { err = resNotFound; goto bail; }
- forwardButton = NewCIconButton(kForwardDefaultButton);
- if (forwardButton == NULL) { err = resNotFound; goto bail; }
- /* get the extra buttons */
- extraButtonIDs = (RBCLRsrcHandle) GetResource(kIconButtonIDListType, kExtraButtonsListID);
- if (extraButtonIDs != NULL) {
- nExtraButtons = (**extraButtonIDs).n;
- if (nExtraButtons > kExtraButtonsMax) nExtraButtons = kExtraButtonsMax;
- for (i=0; i < nExtraButtons; i++) {
- extraButtons[i] = NewCIconButton((**extraButtonIDs).ids[i]);
- if (extraButtons[i] == NULL) { err = resNotFound; goto bail; }
- SetCIconButtonPosition(extraButtons[i], 32 * (3 + i), 0);
- }
- }
-
- /* allocate the window */
- rwin = GetNewCWindow(kRenderingWindowID, NULL, (WindowPtr)(-1));
- if (rwin == NULL) { err = resNotFound; goto bail; }
- SetPort(rwin);
- /* position it on the screen */
- MoveWindow(rwin, gPosition.h + 20, gPosition.v + 50, true);
- gPosition.h = (gPosition.h + 10) % 300;
- gPosition.v = (gPosition.v + 32) % 200;
- /* set up the renderer */
- err = HRNewReference(&rend, kHRRendererHTML32Type, rwin);
- if (err != noErr) goto bail;
- err = HRSetGrowboxCutout(rend, true);
- if (err != noErr) goto bail;
- /* create the history */
- hist = NewHistory();
- if (hist == NULL) { err = memFullErr; goto bail; }
- /* allocate the storage and store a handle to it in the refcon */
- rwv = (RWindowHandle) NewHandleClear(offsetof(RWindowVars, extraButtons) + sizeof(CIconButtonHandle)*nExtraButtons);
- if (rwv == NULL) { err = memFullErr; goto bail; }
- (**rwv).rwindow = rwin;
- (**rwv).renderer = rend;
- (**rwv).history = hist;
- (**rwv).isActive = false;
- (**rwv).bback = backButton;
- (**rwv).bhome = homeButton;
- (**rwv).bforward = forwardButton;
- (**rwv).nExtraButtons = nExtraButtons;
- for (i=0; i<nExtraButtons; i++)
- (**rwv).extraButtons[i] = extraButtons[i];
- SetWRefCon(rwin, (long) rwv);
- /* set up the new links call back */
- if (gNewURLUPP == NULL) {
- gNewURLUPP = NewHRNewURLUPP(MyNewURLProc);
- if (gNewURLUPP == NULL) { err = memFullErr; goto bail; }
- }
- HRRegisterNewURLUPP( gNewURLUPP, rend, rwv);
- /* set up the visited links call back */
- if (gVisitedURLUPP == NULL) {
- gVisitedURLUPP = NewHRWasURLVisitedUPP(MyHRWasURLVisitedProc);
- if (gVisitedURLUPP == NULL) { err = memFullErr; goto bail; }
- }
- HRRegisterWasURLVisitedUPP( gVisitedURLUPP, rend, rwv);
- /* set up the link translation call back */
- if (gTranslateURLUPP == NULL) {
- gTranslateURLUPP = NewHRURLToFSSpecUPP(MyHRURLToFSSpecProc);
- if (gTranslateURLUPP == NULL) { err = memFullErr; goto bail; }
- }
- HRRegisterURLToFSSpecUPP( gTranslateURLUPP, rend, rwv);
- /* add the window to the list of open windows */
- if (gRWFirst == NULL) {
- gRWFirst = gRWLast = rwv;
- } else {
- (**rwv).next = gRWFirst;
- (**gRWFirst).prev = rwv;
- gRWFirst = rwv;
- }
- /* recalculate the window's coordinates and show it */
- RWRecalculateSize(rwin);
- ShowWindow(rwin);
- *rWindow = rwin;
- return noErr;
-
- bail:
- /* if an error occurs, we recover and return the error code */
- if (hist != NULL) DisposeHistory(hist);
- if (rend != NULL) HRDisposeReference(rend);
- if (rwin != NULL) DisposeWindow(rwin);
- if (rwv != NULL) DisposeHandle((Handle) rwv);
- if (backButton != NULL) DisposeCIconButton(backButton);
- if (homeButton != NULL) DisposeCIconButton(homeButton);
- if (forwardButton != NULL) DisposeCIconButton(forwardButton);
- for (i=0; i < nExtraButtons; i++) {
- if (extraButtons[i] != NULL) DisposeCIconButton(extraButtons[i]);
- }
- return err;
- }
-
-
- /* RWCloseWindow closes the rendering window pointed to by
- rWin. */
- void RWCloseWindow(WindowPtr rWin) {
- RWindowHandle rwv;
- short i;
- /* set up locals */
- rwv = (RWindowHandle) GetWRefCon(rWin);
- /* delete the rendering object */
- HRDisposeReference((**rwv).renderer);
- /* delete the history */
- DisposeHistory((**rwv).history);
- /* deallocate the window */
- DisposeWindow((**rwv).rwindow);
- /* delete the icons */
- DisposeCIconButton((**rwv).bback);
- DisposeCIconButton((**rwv).bhome);
- DisposeCIconButton((**rwv).bforward);
- for (i=0; i < (**rwv).nExtraButtons; i++)
- DisposeCIconButton((**rwv).extraButtons[i]);
- /* remove from the rendering window list */
- if ((**rwv).next != NULL)
- (**(**rwv).next).prev = (**rwv).prev;
- else gRWLast = (*rwv)->prev;
- if ((**rwv).prev != NULL)
- (**(**rwv).prev).next = (**rwv).next;
- else gRWFirst = (**rwv).next;
- /* delete storage */
- DisposeHandle((Handle) rwv);
- }
-
-
- /* IsARenderingWindow returns true if rWin points to a rendering
- window created by RWOpen. You should not call any of the routines
- below for windows that are not rendering windows. This routine
- provides a convenient way to tell if a windowptr returned by one
- of the toolbox routines is a rendering window. */
- Boolean IsARenderingWindow(WindowPtr rWin) {
- RWindowHandle rover;
- /* a null pointer cannot refer to a rendering window */
- if (rWin == NULL) return false;
- /* search the list of windows and see if it's there */
- for (rover = gRWFirst; rover != NULL; rover = (**rover).next)
- if (rWin == (**rover).rwindow)
- return true;
- /* if it's not there, return false. */
- return false;
- }
-